/*
 * Copyright 2005-2013 finalist.cn. All rights reserved.
 * Support: http://www.finalist.cn
 * License: http://www.finalist.cn/license
 */
package com.finalist.interceptor;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.finalist.AccessToken;
import com.finalist.WeixinUser;
import com.finalist.entity.Member;
import com.finalist.entity.OpenUnion;
import com.finalist.entity.Member.Gender;
import com.finalist.service.MemberService;
import com.finalist.service.OpenUnionService;
import com.finalist.util.HttpUtil;
import com.finalist.util.JsonUtil;
import com.finalist.util.RestHttpRequestHelper;
import com.finalist.util.WebUtils;







/**
 * Interceptor - 网页授权获取unionId
 * 
 * @author Finalist IT Group
 * @version 3.0
 */
public class WeixinInterceptor extends HandlerInterceptorAdapter
{
	private static final String WX_APP_ID="wx1f8e6c3c87945e87";
	private static final String WX_APP_SECRET="dc304f02af10a771aa1c1b2ae4d1e7ae";
	private static final String GRANTTYPE="authorization_code";
	private static final String WX_OAUTH2_URL="https://api.weixin.qq.com/sns/oauth2/access_token";
	private static final String URL_ACCESS_TOKEN="https://api.weixin.qq.com/cgi-bin/token";
	public static final String URL_USER_INFO = "https://api.weixin.qq.com/cgi-bin/user/info"; 
    private static final Log log = LogFactory.getLog(WeixinInterceptor.class);
    private static Map<String, String> ACCESS_PARAM = new HashMap<String, String>();
    
    private AccessToken token = null;
	private Object tokenMutex = new Object();
	
    @Resource(name = "openUnionServiceImpl")
    private OpenUnionService openUnionService;
    
    @Resource(name = "memberServiceImpl")
    private MemberService memberService;
    
    static {
		ACCESS_PARAM.put("grant_type", "client_credential");
		ACCESS_PARAM.put("appid", WX_APP_ID);
		ACCESS_PARAM.put("secret", WX_APP_SECRET);
	}

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
    	String cookieopenid=WebUtils.getCookie(request, WX_APP_ID+"openid");
    	if(cookieopenid!=null){
    		OpenUnion openUnion=openUnionService.findByopenId(cookieopenid);
			if(openUnion!=null){
				String unionid=openUnion.getUnionId();
				Member member=memberService.findByUnionId(unionid);
				request.setAttribute("currentUser", member);
			}else{
				this.handWeixin(request, response);
			}
    	}else{
    		this.handWeixin(request, response);
    	}
    	 return super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception
    {
        
    }

    
    public WeixinUser getWeixinUser(String openid){
    	synchronized(tokenMutex) {
			if(token == null || !token.isVaid()) {
				log.info("开始调用获取access_token...");
				try {
					String str = HttpUtil.get(URL_ACCESS_TOKEN, ACCESS_PARAM);
					token = JsonUtil.toBean(str, AccessToken.class);
				} catch(Exception e) {
				}
			}
		}
    	log.info("access_token:"+token.getAccess_token());
    	StringBuilder url = new StringBuilder();
		url.append(URL_USER_INFO);
		url.append("?access_token=" + token.getAccess_token());
		url.append("&openid=" + openid);
		url.append("&lang=zh_CN");
		String json=HttpUtil.get(url.toString());
		log.info("userJson"+json);
		if(json!=null){
			return JsonUtil.toBean(json, WeixinUser.class);
		}
    	return null;
    }
    
    
    public void handWeixin(HttpServletRequest request, HttpServletResponse response) throws Exception{
    	String code=request.getParameter("code");
		Map<String, String> paramMap = new HashMap<String, String>();
		paramMap.put("appid", WX_APP_ID);
		paramMap.put("secret", WX_APP_SECRET);
		paramMap.put("code", code);
		paramMap.put("grant_type", GRANTTYPE);
		String restRequest = RestHttpRequestHelper
				.executeHttpPostRequest(WX_OAUTH2_URL, paramMap);
		JSONObject jsonObject = JSONObject.fromObject(restRequest);
		log.info("jsonObject"+jsonObject);
		String openid = (String) jsonObject.get("openid");
		log.info("openid:"+openid);
		if(openid!=null){
			WebUtils.addCookie(request, response, WX_APP_ID+"openid", openid);
			String unionid=null;
			WeixinUser weixinUser=null;
			OpenUnion openUnion=openUnionService.findByopenId(openid);
			//unionid存自己服务器减少调用微信的次数
			if(openUnion!=null){
				unionid=openUnion.getUnionId();
			}else{
				weixinUser=this.getWeixinUser(openid);
				log.info("weixinUser"+weixinUser);
				log.info("nickname"+weixinUser.getNickname());
				log.info("unionid"+weixinUser.getUnionid());
				unionid=weixinUser.getUnionid();
			}
			if(unionid==null){
				log.info("请把公众账号与开放平台绑定");
				return;
			}
			
			log.info("unionid:"+unionid);
			WebUtils.addCookie(request, response, WX_APP_ID+"unionid", unionid);
			Member member=memberService.findByUnionId(unionid);
			log.info("member:"+member);
			
			if(member!=null){
				request.setAttribute("currentUser", member);
			}else{
				Member newMember=new Member();
				newMember.setUsername(weixinUser.getNickname());
				newMember.setPassword("000000");
				if(weixinUser!=null&&weixinUser.getSex()=="1"){
					newMember.setGender(Gender.male);
				}else{
					newMember.setGender(Gender.female);
				}
				newMember.setHeadImgUrl(weixinUser.getHeadimgurl());
				newMember.setPoint(0l);
				newMember.setIsEnabled(true);
				newMember.setAmount(new BigDecimal(0l));
				newMember.setBalance(new BigDecimal(0l));
				newMember.setUnionId(weixinUser.getUnionid());
				memberService.save(newMember);
				OpenUnion newOpenUnion=new OpenUnion();
				newOpenUnion.setOpenId(openid);
				newOpenUnion.setUnionId(unionid);
				openUnionService.save(newOpenUnion);
				request.setAttribute("currentUser", newMember);
			}
		}
    }

}
